#include "TXLib.h"

template <typename T = int>
class Vector_t
{
    private:

        const int START_SIZE = 16;
        T *buffer_;
        int n_;
        int size_;

        void CheckSize ()
        {
            if (n_ >= size_) // Voobshe-to oni ravni
            {
 //               printf ("\nChange Size!\n");
                n_ = size_; // Na vsyakii slychai

                T *old_buffer = buffer_;
                size_ *= 2;
                buffer_ = (T*) malloc (size_ * sizeof(T));
                for (int i = 0; i < n_; i ++) buffer_ [i] = old_buffer [i];
                free (old_buffer);

//                printf ("New Size = %d\n", size_);
            }
        }

    public:

        void clean ()
        {
            n_ = 0;
        }

        int capacity ()
        {
            return size_;
        }

        int size ()
        {
            return n_;
        }

        void push_back (T x)
        {
            CheckSize();
            buffer_ [n_] = x;
            n_ ++;
        }

        void pop_back ()
        {
            if (n_ > 0) n_ --;
        }

        void erase (int i)
        {
            if ((i >= 0) && (i < n_))
            {
                CheckSize();
                for (int k = i; k < (n_ - 1); k ++) buffer_ [k] = buffer_ [k + 1];
                n_ --;
            }
            else
            {
                MessageBox(txWindow(), "Error!", "erase: Out of Data", MB_OK);
            }
        }

        void insert (int i, T x)
        {
            if ((i >= 0) && (i <= n_))
            {
                CheckSize();
                for (int k = (n_ - 1); k >= i; k --) buffer_ [k + 1] = buffer_ [k];
                buffer_ [i] = x;
                n_ ++;
            }
            else
            {
                MessageBox(txWindow(), "Error!", "insert: Out of Data", MB_OK);
            }
        }

        T &at (int i)
        {
            if ((i >= 0) && (i < n_)) return buffer_ [i];
            else
            {
                MessageBox(txWindow(), "Error!", "at: Out of Data", MB_OK);
                return buffer_ [0];
            }
        }

        T &operator[] (int i)
        {
            if ((i >= 0) && (i < n_)) return buffer_ [i];
            else
            {
                MessageBox(txWindow(), "Error!", "at: Out of Data", MB_OK);
                return buffer_ [0];
            }
        }

        Vector_t<T> &operator= (const Vector_t<T> &x)
        {
            n_ = x.n_;
            size_ = x.size_;
            free (buffer_);
            buffer_ = (T*) malloc (size_ * sizeof(T));
            for (int i = 0; i < n_; i++)
            {
                buffer_ [i] = x.buffer_ [i];
            }
            return *this;
        }

        void Print ()
        {
//            printf ("Begin Print (%d)\n", n_);
            for (int i = 0; i < n_; i ++)
                std::cout << buffer_ [i] << ' ';
            printf ("\n");
        }

        Vector_t(const Vector_t <T> &x):
            n_ (x.n_),
            size_ (x.size_)
            {
                buffer_ = (T*) malloc (size_ * sizeof(T));
                for (int i = 0; i < n_; i++)
                {
                    buffer_ [i] = x.buffer_ [i];
                }
            }

        Vector_t():
            n_ (0),
            size_ (START_SIZE)
            {
                buffer_ = (T*) malloc (size_ * sizeof(T));
            }

        Vector_t(int UserSize):
            n_ (UserSize),
            size_ (UserSize)
            {
                buffer_ = (T*) malloc (size_ * sizeof(T));
                for (int i = 0; i < size_; i ++) buffer_ [i] = 0;
            }

        ~Vector_t()
        {
            free (buffer_);
        }
};


template <typename T = int>
class Vector2D_t
{
    private:

        const int START_SIZE = 16;
        Vector_t<T> *buffer_;
        int n_;
        int w_;
        int size_;

        void CheckSize ()
        {
            if (n_ >= size_) // Voobshe-to oni ravni
            {
 //               printf ("\nChange Size!\n");
                n_ = size_; // Na vsyakii slychai

                Vector_t<T> *old_buffer = buffer_;
                size_ *= 2;
                buffer_ = (Vector_t<T>*) malloc (size_ * sizeof(Vector_t<T>));
                for (int i = 0; i < n_; i ++) buffer_ [i] = old_buffer [i];
                free (old_buffer);

//                printf ("New Size = %d\n", size_);
            }
        }

    public:

        int capacity ()
        {
            return size_;
        }

        int size_h ()
        {
            return n_;
        }

        int size_w ()
        {
            return w_;
        }

        void push_back_h (Vector_t<T> &x)
        {
            if (w_ == 0) w_ = x.size();
            if (x.size() == w_)
            {
                CheckSize();
                buffer_ [n_] = x;
                n_ ++;
            }
            else MessageBox(txWindow(), "Error!", "push_back: Error Size of New Vector", MB_OK);
        }

        void push_back_w (Vector_t<T> &x)
        {
            if (x.size() == n_)
            {
                for (int i = 0; i < n_; i ++)
                    {
                        buffer_ [i].push_back(x[i]);
                    }
                w_ ++;
            }
            else MessageBox(txWindow(), "Error!", "push_back: Error Size of New Vector", MB_OK);
        }

        void pop_back_h ()
        {
            if (n_ > 0) n_ --;
        }

        void pop_back_w ()
        {
            for (int i = 0; i < n_; i ++)
            {
                buffer_ [i].pop_back();
            }
            w_ --;
        }

        void erase_h (int i)
        {
            if ((i >= 0) && (i < n_))
            {
                for (int k = i; k < (n_ - 1); k ++) buffer_ [k] = buffer_ [k + 1];
                n_ --;
            }
            else
            {
                MessageBox(txWindow(), "Error!", "erase: Out of Data", MB_OK);
            }
        }

        void erase_w (int i)
        {
            if ((i >= 0) && (i < w_))
            {
                for (int k = 0; k < n_; k ++) buffer_ [k].erase (i);
                w_ --;
            }
            else
            {
                MessageBox(txWindow(), "Error!", "erase: Out of Data", MB_OK);
            }
        }

        T &at (int i)
        {
            if ((i >= 0) && (i < n_)) return buffer_ [i];
            else
            {
                MessageBox(txWindow(), "Error!", "at: Out of Data", MB_OK);
                return buffer_ [0];
            }
        }

        Vector_t<T> &operator[] (int i)
        {
            if ((i >= 0) && (i < n_)) return buffer_ [i];
            else
            {
                MessageBox(txWindow(), "Error!", "at: Out of Data", MB_OK);
                return buffer_ [0];
            }
        }

        Vector2D_t<T> &operator= (const Vector_t<T> &x)
        {
            n_ = x.n_;
            size_ = x.size_;
            free (buffer_);
            buffer_ = (Vector_t<T>*) malloc (size_ * sizeof(Vector_t<T>));
            for (int i = 0; i < n_; i++)
            {
                buffer_ [i] = x.buffer_ [i];
            }
            return *this;
        }

        void Print ()
        {
//            printf ("Begin Print (%d)\n", n_);
            for (int i = 0; i < n_; i ++)
                //std::cout << buffer_ [i] << '\n';
                {
                    buffer_ [i].Print ();
//                    std::cout << '\n';
                }

//            printf ("End\n");
        }

        Vector2D_t(const Vector2D_t <T> &x):
            n_ (x.n_),
            w_ (x.w_),
            size_ (x.size_)
            {
                buffer_ = (Vector_t<T>*) malloc (size_ * sizeof(Vector_t<T>));
                for (int i = 0; i < n_; i++)
                {
                    buffer_ [i] = x.buffer_ [i];
                }
            }

        Vector2D_t():
            n_ (0),
            w_ (0),
            size_ (START_SIZE)
            {
                buffer_ = (Vector_t<T>*) malloc (size_ * sizeof(Vector_t<T>));
            }

        Vector2D_t(int UserH, int UserW):
            n_ (UserH),
            w_ (UserW),
            size_ (UserH)
            {
                buffer_ = (Vector_t<T>*) malloc (size_ * sizeof(Vector_t<T>));
                Vector_t <T> *temp = new Vector_t <T> (w_);
                for (int i = 0; i < n_; i ++)
                {
                    buffer_ [i] = *temp;
                }
                delete temp;
            }

        ~Vector2D_t()
        {
            free (buffer_);
        }

};

void Func (Vector_t <char> v2)
{
    v2.erase (2);
    printf("V2\n");
    v2.Print ();
}


int main ()
{
    //txCreateWindow (800, 600);
    Vector_t <char> v;
    Vector2D_t <char> x;
 //   x.push_back ('f');
    //int i = 0;

    for (int k = 0; k < 4; k ++)
    {
        v.push_back('a' + k);
    }
    x.push_back_h(v);

    v.clean ();
    for (int k = 0; k < 4; k ++)
    {
        v.push_back('b' + k);
    }
    x.push_back_h(v);

    x.Print();

    printf ("%c \n-------\n\n", x [1][2]);

    Vector_t <int> a (3);
    a [0] = 56;
    a.Print();

    printf ("\n---NEW----\n\n");
    Vector2D_t <int> aa (3, 5);

    aa [0][1] = 5;
    aa.push_back_w(a);
    aa.Print ();
/*    for (int k = 0; k < 10; k ++)
    {
        v.push_back('a' + i);
        printf("%d\n", i);
        i ++;
    }
    x = v;
    v.erase (4);
    v [1] = '+';
    x.Print ();
    v.Print ();
    //std::cout << v [5] << '\n' << '\n' << '\n';

    Func (v);

    v.Print ();
    x.Print ();
    */
    return 0;
}
